package com.wiscamp.ninechapters.common.core;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.DateTimeException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.time.temporal.WeekFields;
import java.util.Locale;

public class DateTimeHelper {

    private DateTimeHelper() {
    }

    private static final Logger logger = LoggerFactory.getLogger(ParseHelper.class);

    private static final String DATE_PATTERN = "yyyy-MM-dd";

    private static final String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

    /**
     * 获取格式化的LocalDate字符串
     *
     * @param date
     * @return
     */
    public static String getDateString(LocalDate date) {
        var formatter = DateTimeFormatter.ofPattern(DATE_PATTERN);
        return date.format(formatter);
    }

    /**
     * 获取格式化的LocalDate字符串
     *
     * @param date
     * @param pattern
     * @return
     */
    public static String getDateString(LocalDate date, String pattern) {
        var formatter = DateTimeFormatter.ofPattern(pattern);
        return date.format(formatter);
    }

    /**
     * 获取格式化的LocalDateTime字符串
     *
     * @param dateTime
     * @return
     */
    public static String getDateTimeString(LocalDateTime dateTime) {
        var formatter = DateTimeFormatter.ofPattern(DATE_TIME_PATTERN);
        return dateTime.format(formatter);
    }

    /**
     * 获取格式化的LocalDateTime字符串
     *
     * @param dateTime
     * @param pattern
     * @return
     */
    public static String getDateTimeString(LocalDateTime dateTime, String pattern) {
        var formatter = DateTimeFormatter.ofPattern(pattern);
        return dateTime.format(formatter);
    }

    /**
     * 获取某年某月的最后一天
     *
     * @param year
     * @param month
     * @return
     */
    public static LocalDate getLastDayOfMonth(int year, int month) {
        var dayStart = LocalDate.of(year, month, 1);
        return dayStart.with(TemporalAdjusters.lastDayOfMonth());
    }

    /**
     * 获取某年某月的最后一天的格式化字符串
     *
     * @param year
     * @param month
     * @return
     */
    public static String getLastDayOfMonthString(int year, int month) {
        return getDateString(getLastDayOfMonth(year, month));
    }

    /**
     * 获取某年某月的第一天的格式化字符串
     *
     * @param year
     * @param month
     * @return
     */
    public static LocalDate getFirstDayOfMonth(int year, int month) {
        return LocalDate.of(year, month, 1);
    }

    /**
     * 获取某年某月的第一天的格式化字符串
     *
     * @param year
     * @param month
     * @return
     */
    public static String getFirstDayOfMonthString(int year, int month) {
        return getDateString(getFirstDayOfMonth(year, month));
    }

    /**
     * 获取今天日期的格式化字符串
     *
     * @return
     */
    public static String getTodayDateString() {
        return getDateStringFromNow(0);
    }

    /**
     * 获取明天日期的格式化字符串
     *
     * @return
     */
    public static String getTomorrowDateString() {
        return getDateStringFromNow(1);
    }

    /**
     * 获取昨天日期的格式化字符串
     *
     * @return
     */
    public static String getYesterdayDateString() {
        return getDateStringFromNow(-1);
    }

    /**
     * 获取距离今天若干天日期的格式化字符串
     *
     * @param days
     * @return
     */
    public static String getDateStringFromNow(int days) {
        var now = LocalDate.now();
        var day = now;
        if (days < 0) {
            long minusDays = -days;
            day = now.minusDays(minusDays);
        } else if (days > 0) {
            day = now.plusDays(days);
        }
        return getDateString(day);
    }

    /**
     * 获取某天日期在该年度的周数
     *
     * @param date
     * @return
     */
    public static int getWeekOfYear(LocalDate date) {
        var weekFields = WeekFields.of(Locale.getDefault());
        return date.get(weekFields.weekOfWeekBasedYear());
    }

    public static LocalDate parseDate(String dateText) {
        try {
            return LocalDate.parse(dateText, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        } catch (DateTimeException e) {
            logger.error("Failed to convert the date.", e);
            return null;
        }
    }

    public static LocalDateTime dateTimeOf(int year, int month, int day, int hour, int minute, int second) {
        try {
            return LocalDateTime.of(year, month, day, hour, minute, second);
        } catch (DateTimeException e) {
            logger.error("Failed to convert the date time.", e);
            return null;
        }
    }

    public static LocalDateTime parseDateTime(String dateTimeText) {
        try {
            return LocalDateTime.parse(dateTimeText, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        } catch (DateTimeException e) {
            logger.error("Failed to convert the date time.", e);
            return null;
        }
    }
}
